package com.starsky.common.utils.file;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

/**
 * Description: 配置文件操作工具类
 */
public class ConfigUtil {

	private static final Logger log = LoggerFactory.getLogger(ConfigUtil.class);

	/**
	 * 资源配置信息
	 */
	private static Map<Integer, Map<String, String>> configValues = new HashMap<Integer, Map<String, String>>();

	/**
	 * 获取配置值
	 * @param configName 	资源配置文件名
	 * @param name 			配置名称
	 * @return				返回配置值
	 */
	public static String getString(String configName, String name) {
		return getString(configName, name,null);
	}

	/**
	 * 获取配置值
	 * @param configName 	资源配置文件名
	 * @param name 			配置名称
	 * @param defaultValue	默认值
	 * @return				返回配置值
	 */
	public static String getString(String configName, String name, String defaultValue) {
		Map<String, String> resoure = getResoure(configName);
		//String value = resoure.getOrDefault(name, defaultValue);
		String value = null;
		if(resoure.containsKey(name))
			value = resoure.get(name);
		else value = defaultValue;
		if(value != null && !value.isEmpty())
			value = value.trim();
		return value;
	}

	/**
	 * 获取配置值
	 * @param configName 	资源配置文件名
	 * @param name 			配置名称
	 * @param defaultValue	默认值
	 * @return				返回配置值
	 */
	public static int getInt(String configName, String name, int defaultValue) {
		String valueString = getString(configName, name,String.valueOf(defaultValue));
		return Integer.parseInt(valueString);
	}

	/**
	 * 获取配置值
	 * @param configName 	资源配置文件名
	 * @param name 			配置名称
	 * @param defaultValue	默认值
	 * @return				返回配置值
	 */
	public static long getLong(String configName, String name, long defaultValue) {
		String valueString = getString(configName, name,String.valueOf(defaultValue));
		return Long.parseLong(valueString);
	}

	/**
	 * 获取配置值
	 * @param configName 	资源配置文件名
	 * @param name 			配置名称
	 * @param defaultValue	默认值
	 * @return				返回配置值
	 */
	public static float getFloat(String configName, String name, float defaultValue) {
		String valueString = getString(configName, name,String.valueOf(defaultValue));
		return Float.parseFloat(valueString);
	}

	/**
	 * 获取配置值
	 * @param configName 	资源配置文件名
	 * @param name 			配置名称
	 * @param defaultValue	默认值
	 * @return				返回配置值
	 */
	public static double getDouble(String configName, String name, double defaultValue) {
		String valueString = getString(configName, name,String.valueOf(defaultValue));
		return Double.parseDouble(valueString);
	}

	/**
	 * 获取配置值
	 * @param configName 	资源配置文件名
	 * @param name 			配置名称
	 * @param defaultValue	默认值
	 * @return				返回配置值
	 */
	public static boolean getBoolean(String configName, String name, boolean defaultValue) {
		String valueString = getString(configName, name,String.valueOf(defaultValue));
		return Boolean.parseBoolean(valueString);
	}

	/**
	 * 获取配置值
	 * @param configName 	资源配置文件名
	 * @param name 			配置名称
	 * @param defaultValue	默认值
	 * @return				返回配置值
	 */
	public static <T extends Enum<T>> T getEnum(String configName, String name, T defaultValue) {
		String valueString = getString(configName, name);
		if (valueString != null && !valueString.isEmpty())
			defaultValue = Enum.valueOf(defaultValue.getDeclaringClass(), valueString);
		return defaultValue;
	}
	
	/**
	 * 获取所有配置值
	 * @param configName 资源配置文件名
	 * @return 返回所有配置值
	 */
	private static Map<String, String> getResoure(String configName){
		int code = configName.trim().hashCode();
		if (!configValues.containsKey(code)) {
			synchronized (lockObj) {
				if (!configValues.containsKey(code)) {
					Map<String, String> values = getAllProperties(configName);
					configValues.put(code, values);
				}
			}
		}
		return configValues.get(code);
	}
	
	/**
	 * 获取所有配置值
	 * @param rcn 资源配置名称
	 * @return	返回所有配置值
	 */
	private static Map<String, String> getAllProperties(String rcn) {
		Map<String, String> map = new HashMap<String, String>(); // 保存所有的键值
		Set<Entry<Object, Object>> objs = getProperties(rcn).entrySet();
		for (Entry<Object, Object> obj : objs) {
			Object key = obj.getKey();
			Object value = obj.getValue();
			if (key != null && !key.toString().isEmpty())
				if (!map.containsKey(key))
					map.put(key.toString().trim(), value.toString().trim());
		}
		return map;
	}

	//
	// public void setValue(String name, String value) throws IOException {
	// Properties prop = new Properties();
	// InputStream fis = new FileInputStream(this.configPath);
	// // 从输入流中读取属性列表（键和元素对）
	// prop.load(fis);
	// // 调用 Hashtable 的方法 put。使用 getProperty 方法提供并行性。
	// // 强制要求为属性的键和值使用字符串。返回值是 Hashtable 调用 put 的结果。
	// OutputStream fos = new FileOutputStream(this.configPath);
	// prop.setProperty(name, value);
	// // 以适合使用 load 方法加载到 Properties 表中的格式，
	// // 将此 Properties 表中的属性列表（键和元素对）写入输出流
	// prop.store(fos, "last update");
	// // 关闭文件
	// fis.close();
	// fos.close();
	// }

	private static Object lockObj = "";

	/**
	 * 
	 * @param rcn 资源配置名称
	 * @return
	 */
	private static Properties getProperties(String rcn) {
		Properties props = new Properties();
		InputStream in = getConfResourceAsInputStream(rcn);
		try {
			if (in != null) {
				props.load(in);
				// 关闭资源
				in.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			log.error(e.getMessage());
		}
		return props;
	}

	/**
	 * 
	 * @param rcn 资源配置名称
	 * @return
	 */
	public static URL getResource(String rcn) {
		ClassLoader cL = Thread.currentThread().getContextClassLoader();
		if (cL == null) {
			cL = ConfigUtil.class.getClassLoader();
		}
		return cL.getResource(rcn);
	}

	/**
	 * 
	 * @param rcn 资源配置名称
	 * @return
	 */
	public static InputStream getConfResourceAsInputStream(String rcn) {
		try {
			URL url = getResource(rcn);

			if (url == null) {
				log.error(rcn + " not found");
				return null;
			} else {
				log.info("found resource " + rcn + " at " + url);
			}

			return url.openStream();
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 
	 * @param rcn 资源配置名称
	 * @return
	 */
	public static Reader getConfResourceAsReader(String rcn) {
		try {
			URL url = getResource(rcn);

			if (url == null) {
				log.info(rcn + " not found");
				return null;
			} else {
				log.info("found resource " + rcn + " at " + url);
			}

			return new InputStreamReader(url.openStream());
		} catch (Exception e) {
			return null;
		}
	}
}
